#include "mapwidget.h"
#include <QPainter>
#include <QWheelEvent>
#include <QHash>
#include <QPair>
#include <QtMath>
#include<QPixmap>
#include <QRectF>
#include <QtConcurrent/QtConcurrentRun>
#include <unordered_set>



MapWidget::MapWidget(QWidget *parent) : QWidget(parent) {
    connect(this, &MapWidget::mapGenerationComplete, this, [this]() {
        connect(this, &MapWidget::mapGenerationComplete, this, [this]() {
            // 初始化为地图中心点
            centerX = 500;
            centerY = 500;
            zoomLevel = 1.0; // 初始缩放级别
            update();
        });
    });
    generateNewMap(10000); // 生成10000个顶点
}

void MapWidget::generateNewMap(int numVertex) {
    QtConcurrent::run([this, numVertex]() {
        map.generatemap(numVertex);
        emit mapGenerationComplete(); // 确保生成完成后发射信号
    });
}

void MapWidget::paintEvent(QPaintEvent* event) {
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::SmoothPixmapTransform);
    painter.setRenderHint(QPainter::Antialiasing, true);

    // 统一缩放和中心点参数
    const double scaleFactor = qPow(1.2, zoomLevel);
    const QPixmap bg(":/resources/background.jpg");

    // ==== 绘制背景 ====
    painter.save();
    painter.translate(width() / 2.0, height() / 2.0);
    painter.scale(scaleFactor, scaleFactor);
    painter.translate(-centerX, -centerY);

    // 计算背景图像的大小和位置
    double bgWidth = bg.width();
    double bgHeight = bg.height();

    // 计算窗口的宽高比
    double aspectRatio = bgWidth / bgHeight;
    double widgetAspectRatio = width() / static_cast<double>(height());

    // 根据窗口比例调整背景图像的绘制尺寸
    QRectF bgRect;
    if (widgetAspectRatio > aspectRatio) {
        // 窗口更宽，按高度填充背景
        bgRect = QRectF(-bgHeight * widgetAspectRatio / 2, -bgHeight / 2, bgHeight * widgetAspectRatio, bgHeight);
    } else {
        // 窗口更高，按宽度填充背景
        bgRect = QRectF(-bgWidth / 2, -bgWidth / aspectRatio / 2, bgWidth, bgWidth / aspectRatio);
    }

    // 确保使用QPixmap的scaled()来调整背景图片大小
    QPixmap scaledBg = bg.scaled(bgRect.size().toSize(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

    // 绘制背景
    painter.drawPixmap(bgRect.topLeft(), scaledBg);
    painter.restore();

    // ==== 绘制地图内容（保持原有逻辑） ====
    painter.translate(width() / 2.0, height() / 2.0);
    painter.scale(scaleFactor, scaleFactor);
    painter.translate(-centerX, -centerY);

    // 计算可见区域
    const double visibleWidth = width() / scaleFactor * 1.3;
    const double visibleHeight = height() / scaleFactor * 1.3;
    QRectF visibleRect(
        centerX - visibleWidth / 2,
        centerY - visibleHeight / 2,
        visibleWidth,
        visibleHeight
        );

    // 绘制边（分普通边和高亮边）
    QVector<QLineF> normalLines, highlightLines;
    QSet<Vertex*> visibleVertices;
    const int gridSize = map.gridSize;
    const int bufferCells = 1;

    // 第一遍循环：收集可见顶点
    bool showFullDetails = (zoomLevel >= 1);
    const int skipStep = showFullDetails ? 1 : 10;
    int vertexCount = 0;

    for (const auto& v : map.getVertices()) {
        // 顶点过滤逻辑
        if (!map.showAllEdges) {
            if (v != map.currentTarget &&
                !std::count(map.currentNearVertices.begin(),
                            map.currentNearVertices.end(), v)) continue;
        }
        if (vertexCount++ % skipStep != 0) continue;
        visibleVertices.insert(v);
    }

    // 第二遍循环：收集需要绘制的边
    const bool showEdges = zoomLevel >= 1.5; // 缩放级别≥1时显示边
    if (showEdges) {
        const int minGridX = static_cast<int>((visibleRect.left() - gridSize*bufferCells)/gridSize);
        const int maxGridX = static_cast<int>((visibleRect.right() + gridSize*bufferCells)/gridSize);
        const int minGridY = static_cast<int>((visibleRect.top() - gridSize*bufferCells)/gridSize);
        const int maxGridY = static_cast<int>((visibleRect.bottom() + gridSize*bufferCells)/gridSize);

        for (int x = minGridX; x <= maxGridX; ++x) {
            for (int y = minGridY; y <= maxGridY; ++y) {
                const auto gridKey = std::make_pair(x, y);
                if (map.gridIndex.find(gridKey) != map.gridIndex.end()) {
                    for (Edge* edge : map.gridIndex.at(gridKey)) {
                        const bool startVisible = visibleVertices.contains(edge->start);
                        const bool endVisible = visibleVertices.contains(edge->end);

                        if (startVisible && endVisible) {
                            QLineF line(edge->start->x, edge->start->y, edge->end->x, edge->end->y);

                            if (std::find(map.visibleEdges.begin(),
                                          map.visibleEdges.end(), edge) != map.visibleEdges.end()) {
                                highlightLines.append(line);
                            } else {
                                normalLines.append(line);
                            }
                        }
                    }
                }
            }
        }
    }

    // 绘制普通边
    painter.setPen(QPen(Qt::black, 1.0 / scaleFactor));
    if (!normalLines.isEmpty()) {
        painter.drawLines(normalLines.data(), normalLines.size());
    }

    // 绘制高亮边
    painter.setPen(QPen(Qt::darkRed, 3.0 / scaleFactor));
    if (!highlightLines.isEmpty()) {
        painter.drawLines(highlightLines.data(), highlightLines.size());
    }

    // 绘制顶点和编号（合并到之前的可见顶点集合）
    painter.setPen(Qt::NoPen);
    const double pointSize = 5.0 / scaleFactor;
    QHash<QPair<int, int>, bool> textPositions;
    int drawCount = 0;

    for (const auto& v : visibleVertices) {
        painter.setBrush(v == map.currentTarget ? Qt::red : Qt::blue);
        painter.drawEllipse(QPointF(v->x, v->y), pointSize, pointSize);

        if (zoomLevel >= 1) {
            QFont font = painter.font();
            font.setPixelSize(10);
            painter.setFont(font);
            painter.setPen(Qt::black);

            QPointF textPos(v->x + 5/scaleFactor, v->y - 5/scaleFactor);
            QPair<int, int> gridPos(textPos.x()/30, textPos.y()/15);

            if (!textPositions.contains(gridPos)) {
                textPositions.insert(gridPos, true);
                painter.drawText(textPos, QString::number(v->id));
            }
        }

        // 限制最大绘制数量
        if (++drawCount > 5000) break;
    }
    // 绘制高亮边（路径）
    painter.setPen(QPen(Qt::darkGreen, 3.0 / scaleFactor)); // 使用绿色高亮路径
    if (!map.visibleEdges.empty()) {
        QVector<QLineF> pathLines;
        for (Edge* edge : map.visibleEdges) {
            pathLines.append(QLineF(edge->start->x, edge->start->y, edge->end->x, edge->end->y));
        }
        painter.drawLines(pathLines);
    }
}

// ========== 3. 滚轮缩放事件（支持更大缩放范围） ==========
void MapWidget::wheelEvent(QWheelEvent* event) {
    const QPoint numDegrees = event->angleDelta() / 8;
    if (!numDegrees.isNull()) {
        const QPointF mouseScenePos = mapToScene(event->position());
        const double oldScale = qPow(1.2, zoomLevel);

        // 更新缩放级别（0~10）
        zoomLevel += (numDegrees.y() > 0) ? 0.5 : -0.5;
        zoomLevel = qBound(0.0, zoomLevel, 10.0);

        // 计算新中心
        const double newScale = qPow(1.2, zoomLevel);
        centerX = mouseScenePos.x() - (mouseScenePos.x() - centerX) * (newScale / oldScale);
        centerY = mouseScenePos.y() - (mouseScenePos.y() - centerY) * (newScale / oldScale);

        update();
    }
    event->accept();
}
//鼠标按下事件
void MapWidget::mousePressEvent(QMouseEvent* event) {
    if (event->button() == Qt::LeftButton) {
        lastDragPos = event->pos();  // 记录拖拽起始位置
        isDragging = true;

        // 显示抓手光标
        setCursor(Qt::ClosedHandCursor);
    }
    QWidget::mousePressEvent(event);
}

//鼠标移动事件
void MapWidget::mouseMoveEvent(QMouseEvent* event) {
    if (isDragging) {
        const QPoint delta = event->pos() - lastDragPos;
        lastDragPos = event->pos();

        // 计算实际移动距离（考虑当前缩放级别）
        const double scaleFactor = pow(1.2, zoomLevel);
        centerX -= delta.x() / scaleFactor;
        centerY -= delta.y() / scaleFactor;

        update(); // 触发重绘
    }
    QWidget::mouseMoveEvent(event);
}

//辅助函数：屏幕坐标转场景坐标
QPointF MapWidget::mapToScene(const QPointF &screenPos) const {
    const double scaleFactor = pow(1.2, zoomLevel);
    return QPointF(
        (screenPos.x() - width()/2.0) / scaleFactor + centerX,
        (screenPos.y() - height()/2.0) / scaleFactor + centerY
        );
}
